package com.zeddy.android.HarrisVoice;

/**
 * @author Zeddy Chirombe
 *
 */
/*
 * @Filename: 	HarrisBiometrics.java
 * @Classname: 	HarrisBiometrics
 * @Author:		i.z.chirombe@wustl.edu
 * 
 * @Description:	This class take the url from the incoming request, loads the
 * 				corresponding image located on the sdcard, compute the biometric 
 * 				signature, and reply back to the caller. 
 * 
 * 				Before this application can successfully work, ensure the sdcard is
 * 				is accessible, and is readable, otherwise you will get permission 
 * 				denied error. One way to fix this is to disable and runnable 
 * 				debugability on the android phone. reset the adb, and then 
 * 				reset port forwarding.
 */


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.media.FaceDetector;
import android.os.Handler;
import android.util.Log;
import android.widget.TextView;

public class HarrisBiometrics {
	private static final String TAG = "BIO";
	private static final boolean DEBUG = true;

	public enum BiometricErrors { SUCCESS, FILE_NOTFOUND, NO_FACES_DETECTED,
		SECURITY_EXCEPTION, IOEXCEPTION};
	private static final int NUM_FACES = 1; // max is 64

	private FaceDetector arrayFaces;
	private FaceDetector.Face getAllFaces[] = new FaceDetector.Face[NUM_FACES];
	private FaceDetector.Face getFace = null;
	
	private PointF eyesMidPts[] = new PointF[NUM_FACES];
	private float  eyesDistance[] = new float[NUM_FACES];	
	private int picWidth, picHeight;
	
	private Bitmap sourceImage = null;
	
	private Handler activityHandler = null;
	private TextView logView = null;
	
	public HarrisBiometrics(Handler _handler, TextView _logView) { 
		activityHandler = _handler;
		logView = _logView;
	}
	
	public BiometricErrors faceDetect(HarrisMessage harrisMsg, String imageUrl) {
	    FileInputStream in;
	    BufferedInputStream buf;
        try {
       	    in = new FileInputStream(imageUrl);
            buf = new BufferedInputStream(in);
            sourceImage = BitmapFactory.decodeStream(buf);
            
            /* free SD Card Space when finished */
            File file = new File(imageUrl);
            if(!file.delete()) {
            	showPost("Error Deleting Image file - "+imageUrl);
            }
            file = null;
            if (in != null) {
            	in.close();
            }
            if (buf != null) {
            	buf.close();
            }
        } catch (Exception e) {
        	String error = "Error reading file: " + e.toString();
            showPost(error);
            harrisMsg.add_entry(error);
            cancel();
            return BiometricErrors.FILE_NOTFOUND;
        }

		picWidth = sourceImage.getWidth();
		picHeight = sourceImage.getHeight();
		
		arrayFaces = new FaceDetector( picWidth, picHeight, NUM_FACES );
		arrayFaces.findFaces(sourceImage, getAllFaces);
		sourceImage.recycle();
		
		int i = 0;
		if(getAllFaces.length <= 0) {
			showPost("No Faces Detected.....");
			cancel();
			return BiometricErrors.NO_FACES_DETECTED;
		}
		getFace = getAllFaces[i];
		try {
			PointF eyesMP = new PointF();
			getFace.getMidPoint(eyesMP);
			eyesDistance[i] = getFace.eyesDistance();
			eyesMidPts[i] = eyesMP;
			//msgType:uname:<confidence>:<EyesDistance>:<eyesMidPts.x>:<eyesMidPts.y>:<imageUrl>
			harrisMsg.add_entry(""+getFace.confidence());
			harrisMsg.add_entry(""+getFace.eyesDistance());
			harrisMsg.add_entry(""+eyesMidPts[i].x);
			harrisMsg.add_entry(""+eyesMidPts[i].y);
			harrisMsg.add_entry(""+picWidth);
			harrisMsg.add_entry(""+picHeight);
			harrisMsg.add_entry(imageUrl);
			cancel();
			eyesMP = null;
			return BiometricErrors.SUCCESS;
		}
		catch (Exception e)
		{
			showPost(i + " is null");
		}
		cancel();
		return BiometricErrors.IOEXCEPTION;
	}
	public void cancel() {
		sourceImage = null;
		arrayFaces = null;
		getFace = null;	
	}
	public void showPost(final String msg) {
		if(DEBUG) { Log.e(TAG,msg);}
		activityHandler.post(new Runnable() {
			@Override
			public void run() {
				try {
					logView.setText(msg+System.getProperty("line.separator")+logView.getText());
				} catch (NullPointerException e) {
					//if(DEBUG) Log.e(TAG, "showPost()::"+e);
				} catch (Exception e) {
					//if(DEBUG) Log.e(TAG, "showPost()::"+e);
				}
			}	
		});
	}
}

